﻿//Copyright (c) Microsoft Corporation. All rights reserved.

using System.Collections.Generic;

namespace Microsoft.Ted.Wacel.Base
{
    public class MasterDetails<M,D> : CloudDataStructure
    {
        private Dictionary<M> mMasters;
        private Dictionary<string, Dictionary<D>> mDetails = new Dictionary<string, Dictionary<D>>(); //TODO:Eviction needed

        public MasterDetails(string name, IDataProvider dataProvider, ILockProvider lockProvider)
            :base(name, dataProvider, lockProvider)
        {
            mMasters = new Dictionary<M>(name, dataProvider, lockProvider);
        }
        public void Add(string key, M value)
        {
            mMasters.Add(key, value);
        }
        public M SafeGet(string key, M defaultValue)
        {
            return mMasters.SafeGet(key, defaultValue);
        }
        public void Delete(string key)
        {
            DeleteDetails(key);
            mMasters.Delete(key);
        }
        public void DeleteDetails(string key)
        {
            //TODO: clear underlying data
            mDetails.Remove(key);
        }
        public List<KeyValuePair<string,D>> GetDetails(string key)
        {
            if (!mDetails.ContainsKey(key))
                mDetails.Add(key, new Dictionary<D>(Name + key, MyDataProvider.Clone(Name + key), MyLockProvider));
            return mDetails[key].GetAll(partition:key, typeHint:typeof(D));
        }
        public void UpdateDetails(string key, List<KeyValuePair<string,D>> values)
        {
            if (!mDetails.ContainsKey(key))
                mDetails.Add(key, new Dictionary<D>(Name + key, MyDataProvider.Clone(Name + key), MyLockProvider));
            mDetails[key].BulkPut(values,partition:key);
        }
        public void MergeDetails(string key, List<KeyValuePair<string,D>> values)
        {
            if (!mDetails.ContainsKey(key))
                mDetails.Add(key, new Dictionary<D>(Name + key, MyDataProvider.Clone(Name + key), MyLockProvider));
            var existingList = GetDetails(key);
            List<string> keys = new List<string>();
            foreach (var item in existingList)
                keys.Add(item.Key);
            List<KeyValuePair<string,D>> delta = new List<KeyValuePair<string,D>>();
            foreach(var value in values)
            {
                if (keys.IndexOf(value.Key) < 0) //TODO: Updated items as well?
                {
                    delta.Add(value);
                    keys.Add(value.Key);
                }
            }
            mDetails[key].BulkPut(delta, partition:key);
        }
        public void Clear()
        {
            mMasters.Clear();
            foreach (var detail in mDetails.Values)
                detail.Clear();
            mDetails.Clear();
        }
    }
}
